<Project Sdk="Microsoft.Build.NoTargets">
  <PropertyGroup>
    <!-- FIXME: clean up the duplication with libraries Directory.Build.props -->
    <PackageRID>wasi-wasm</PackageRID>
    <NativeBinDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'native', '$(NetCoreAppCurrent)-$(TargetOS)-$(Configuration)-$(TargetArchitecture)'))</NativeBinDir>
  </PropertyGroup>

  <PropertyGroup>
    <ICULibDir Condition="'$(WasmEnableThreads)' != 'true'">$([MSBuild]::NormalizeDirectory('$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)', 'runtimes', 'wasi-wasm', 'native', 'lib'))</ICULibDir>
    <ICULibDir Condition="'$(WasmEnableThreads)' == 'true'">$([MSBuild]::NormalizeDirectory('$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)', 'runtimes', 'wasi-wasm-threads', 'native', 'lib'))</ICULibDir>
    <WasmEnableSIMD Condition="'$(WasmEnableSIMD)' == ''">false</WasmEnableSIMD>
    <FilterSystemTimeZones Condition="'$(FilterSystemTimeZones)' == ''">false</FilterSystemTimeZones>
    <WasiObjDir>$(ArtifactsObjDir)wasi</WasiObjDir>
    <_WasiDefaultsRspPath>$(NativeBinDir)src\wasi-default.rsp</_WasiDefaultsRspPath>
    <_WasiCompileRspPath>$(NativeBinDir)src\wasi-compile.rsp</_WasiCompileRspPath>
    <_WasiLinkRspPath>$(NativeBinDir)src\wasi-link.rsp</_WasiLinkRspPath>
    <WasmNativeStrip Condition="'$(ContinuousIntegrationBuild)' == 'true'">false</WasmNativeStrip>
    <WasiSdkRoot Condition="'$(WasiSdkRoot)' == ''">$(WASI_SDK_PATH)</WasiSdkRoot>
    <WasiClang>$(WasiSdkRoot)\bin\clang</WasiClang>
    <WasiClang Condition="$([MSBuild]::IsOSPlatform('Windows'))">$(WasiClang).exe</WasiClang>
    <WasiLLVMAr>$(WasiSdkRoot)\bin\llvm-ar</WasiLLVMAr>
    <WasiLLVMAr Condition="$([MSBuild]::IsOSPlatform('Windows'))">$(WasiLLVMAr).exe</WasiLLVMAr>
  </PropertyGroup>

  <Target Name="CheckEnv">
    <Error Condition="'$(TargetArchitecture)' != 'wasm'" Text="Expected TargetArchitecture==wasm, got '$(TargetArchitecture)'"/>
    <Error Condition="'$(TargetOS)' != 'wasi'" Text="Expected TargetOS==wasi, got '$(TargetOS)'"/>
    <Error Condition="'$(WASI_SDK_PATH)' == ''" Text="The WASI_SDK_PATH environment variable should be set pointing to the WASI SDK root dir."/>
  </Target>

  <ItemGroup>
    <PackageReference Include="Microsoft.NETCore.Runtime.ICU.Transport" PrivateAssets="all" Version="$(MicrosoftNETCoreRuntimeICUTransportVersion)" GeneratePathProperty="true" />
    <PackageReference Include="System.Runtime.TimeZoneData" PrivateAssets="all" Version="$(SystemRuntimeTimeZoneDataVersion)" GeneratePathProperty="true" />
  </ItemGroup>


  <UsingTask TaskName="ManagedToNativeGenerator" AssemblyFile="$(WasmAppBuilderTasksAssemblyPath)" />
  <Target Name="GenerateManagedToNative" DependsOnTargets="CheckEnv;ResolveLibrariesFromLocalBuild">
    <PropertyGroup>
      <WasmPInvokeTablePath>$(WasiObjDir)\pinvoke-table.h</WasmPInvokeTablePath>
      <WasmInterpToNativeTablePath>$(WasiObjDir)\wasm_m2n_invoke.g.h</WasmInterpToNativeTablePath>
    </PropertyGroup>

    <ItemGroup>
      <WasmPInvokeModule Include="libSystem.Native" />
      <WasmPInvokeModule Include="libSystem.IO.Compression.Native" />
      <WasmPInvokeModule Include="libSystem.Globalization.Native" />
      <WasmPInvokeAssembly Include="@(LibrariesRuntimeFiles)" Condition="'%(Extension)' == '.dll' and '%(IsNative)' != 'true'" />
    </ItemGroup>

    <!-- Retrieve CoreLib's targetpath via GetTargetPath as it isn't binplaced yet. -->
    <MSBuild Projects="$(CoreLibProject)"
             Targets="GetTargetPath">
      <Output TaskParameter="TargetOutputs" ItemName="WasmPInvokeAssembly" />
    </MSBuild>

    <MakeDir Directories="$(WasiObjDir)" Condition="!Exists('$(WasiObjDir)')" />

    <ManagedToNativeGenerator
      Assemblies="@(WasmPInvokeAssembly)"
      PInvokeModules="@(WasmPInvokeModule)"
      PInvokeOutputPath="$(WasmPInvokeTablePath)"
      InterpToNativeOutputPath="$(WasmInterpToNativeTablePath)">
      <Output TaskParameter="FileWrites" ItemName="FileWrites" />
    </ManagedToNativeGenerator>
  </Target>

  <UsingTask TaskName="EmitBundleObjectFiles" AssemblyFile="$(MonoTargetsTasksAssemblyPath)" />
  <Target Name="GenerateTimezonesArchive" Returns="@(_WasmArchivedTimezones)" Condition="'$(InvariantTimezone)' != 'true'">
    <PropertyGroup>
      <_WasmTimezonesPath>$([MSBuild]::NormalizePath('$(PkgSystem_Runtime_TimeZoneData)', 'contentFiles', 'any', 'any', 'data'))</_WasmTimezonesPath>
      <_WasmTimezonesBundleObjectFile>wasm-bundled-timezones.o</_WasmTimezonesBundleObjectFile>
      <_WasmTimezonesBundleArchive>$(WasiObjDir)\wasm-bundled-timezones.a</_WasmTimezonesBundleArchive>
      <_WasmTimezonesArchiveRsp>$(WasiObjDir)\wasm-bundled-timezones-archive.rsp</_WasmTimezonesArchiveRsp>
    </PropertyGroup>
    <ItemGroup>
      <_WasmTimezonesInternal Include="$(_WasmTimezonesPath)\**\*.*" WasmRole="Timezone"/>
    </ItemGroup>
    <ItemGroup>
      <_WasmTimezonesInternal Update="@(_WasmTimezonesInternal)">
        <RegisteredName>/usr/share/zoneinfo/$([MSBuild]::MakeRelative($(_WasmTimezonesPath), %(_WasmTimezonesInternal.Identity)).Replace('\','/'))</RegisteredName>
      </_WasmTimezonesInternal>
    </ItemGroup>
    <!-- TODO make this incremental compilation -->
    <EmitBundleObjectFiles
      FilesToBundle="@(_WasmTimezonesInternal)"
      ClangExecutable="$(WasiClang)"
      BundleRegistrationFunctionName="mono_register_timezones_bundle"
      BundleFile="$(_WasmTimezonesBundleObjectFile)"
      OutputDirectory="$(WasiObjDir)">
      <Output TaskParameter="BundledResources" ItemName="BundledWasiTimezones" />
    </EmitBundleObjectFiles>
    <ItemGroup>
      <WasmBundleTimezonesObjects Include="$([MSBuild]::MakeRelative($(WasiObjDir), %(BundledWasiTimezones.DestinationFile)).Replace('\','/'))" />
      <WasmBundleTimezonesObjects Include="$(_WasmTimezonesBundleObjectFile)" />
    </ItemGroup>
    <WriteLinesToFile File="$(_WasmTimezonesArchiveRsp)"
      Overwrite="true"
      Lines="@(WasmBundleTimezonesObjects, ' ')"
      WriteOnlyWhenDifferent="true" />
    <Exec Command="$(WasiLLVMAr) cs -r $(_WasmTimezonesBundleArchive) @$(_WasmTimezonesArchiveRsp)" WorkingDirectory="$(WasiObjDir)" />

    <ItemGroup>
      <_WasmArchivedTimezones Include="$(_WasmTimezonesBundleArchive)" />
    </ItemGroup>

    <!-- Clean up the bundle-objects dir - remove anything we no longer need -->
    <ItemGroup>
      <_WasmBundleTimezonesToDelete Include="$(_WasmIntermediateOutputPath)*.o" />
      <_WasmBundleTimezonesToDelete Remove="$(WasiObjDir)\$(_WasmTimezonesBundleObjectFile)" />
      <_WasmBundleTimezonesToDelete Remove="%(BundledWasiTimezones.DestinationFile)" />
    </ItemGroup>
    <Delete Files="@(_WasmBundleTimezonesToDelete)" />
  </Target>

  <Target Name="GenerateWasiPropsAndRspFiles">

    <!-- Generate wasm-props.json -->
    <ItemGroup>
      <!-- TODOWASI
      <_WasiLinkFlags Include="-Wl, - - allow-undefined"/>
      -Wl,- - export=malloc, - - export=free, - - export=__heap_base, - - export=__data_end \
      -Wl,-z
      -->
    </ItemGroup>

    <ItemGroup Condition="'$(WasmEnableThreads)' == 'true'">
      <WasmOptConfigurationFlags Include="--enable-threads;--enable-bulk-memory;--enable-sign-ext" />
    </ItemGroup>

    <ItemGroup>
      <_WasiFlags Include="@(_WasiCommonFlags)" />

      <_WasiCompileFlags Condition="'$(WasmEnableThreads)' == 'true'" Include="-I$([MSBuild]::NormalizePath('$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)', 'runtimes', 'wasi-wasm-threads', 'native', 'include').Replace('\','/'))"/>
      <_WasiCompileFlags Condition="'$(WasmEnableThreads)' != 'true'" Include="-I$([MSBuild]::NormalizePath('$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)', 'runtimes', 'wasi-wasm', 'native', 'include').Replace('\','/'))"/>
      <_WasiCompileFlags Include="-I$([MSBuild]::NormalizePath('$(WasiProjectRoot)', 'include').Replace('\','/'))"/>
      <_WasiCompileFlags Include="-I$([MSBuild]::NormalizePath('$(WasiProjectRoot)', 'mono-include').Replace('\','/'))"/>
      <_WasiCompileFlags Include="-I$([MSBuild]::NormalizePath('$(RepoRoot)', 'src', 'native', 'public').Replace('\','/'))"/>
      <_WasiCompileFlags Include="-I$([MSBuild]::NormalizePath('$(MonoProjectRoot)', 'mono', 'eglib').Replace('\','/'))"/>
      <_WasiCompileFlags Include="-D_WASI_EMULATED_PROCESS_CLOCKS"/>
      <_WasiCompileFlags Include="-D_WASI_EMULATED_SIGNAL"/>
      <_WasiCompileFlags Include="-D_WASI_EMULATED_MMAN"/>
      <!-- keep in sync with src\mono\wasi\build\WasiApp.Native.targets -->
      <!-- keep stack-size in sync with wasm_get_stack_size until after https://github.com/llvm/llvm-project/commit/1532be98f99384990544bd5289ba339bca61e15b in WASI SDK -->
      <_WasiLinkFlags Include="-Wl,-z,stack-size=8388608,--initial-memory=52428800,-lwasi-emulated-process-clocks,-lwasi-emulated-signal,-lwasi-emulated-mman"/>
    </ItemGroup>

    <PropertyGroup>
      <_WasiPropsJson>
<![CDATA[
{
  "items": {
    "WasmOptConfigurationFlags": [@(WasmOptConfigurationFlags -> '%22%(Identity)%22', ',')],
  }
}
]]>
      </_WasiPropsJson>
    </PropertyGroup>

    <WriteLinesToFile File="$(NativeBinDir)src\wasm-props.json"
                      Lines="$(_WasiPropsJson)"
                      Overwrite="true"
                      WriteOnlyWhenDifferent="true" />

    <WriteLinesToFile File="$(_WasiDefaultsRspPath)"
                      Lines="@(_WasiFlags)"
                      WriteOnlyWhenDifferent="true"
                      Overwrite="true" />
    <WriteLinesToFile File="$(_WasiCompileRspPath)"
                      Lines="@(_WasiCompileFlags)"
                      WriteOnlyWhenDifferent="true"
                      Overwrite="true" />
    <WriteLinesToFile File="$(_WasiLinkRspPath)"
                      Lines="@(_WasiLinkFlags)"
                      WriteOnlyWhenDifferent="true"
                      Overwrite="true" />
  </Target>


  <!-- This is a documented target that is invoked by developers in their innerloop work. -->
  <Target Name="BuildWasiRuntimes"
          AfterTargets="Build"
          DependsOnTargets="GenerateWasiPropsAndRspFiles;GenerateManagedToNative;GenerateTimezonesArchive">

    <ItemGroup>
      <ICULibNativeFiles Include="$(ICULibDir)/libicuuc.a;
                                  $(ICULibDir)/libicui18n.a;
                                  $(ICULibDir)/libicudata.a" />
      <ICULibFiles Include="$(ICULibDir)/*.dat" />
    </ItemGroup>
    <PropertyGroup>
      <PInvokeTableFile>$(WasiObjDir)\pinvoke-table.h</PInvokeTableFile>
      <InterpToNativeTableFile>$(WasiObjDir)\wasm_m2n_invoke.g.h</InterpToNativeTableFile>
      <WASI_SDK_PATH>$([MSBuild]::EnsureTrailingSlash('$(WASI_SDK_PATH)').Replace('\', '/'))</WASI_SDK_PATH>

      <CMakeConfigurationWasiFlags Condition="'$(Configuration)' == 'Debug'">-g -Os -DDEBUG=1 -DENABLE_AOT_PROFILER=1</CMakeConfigurationWasiFlags>
      <CMakeConfigurationWasiFlags Condition="'$(Configuration)' == 'Release'">-Oz </CMakeConfigurationWasiFlags>

      <CMakeConfigurationLinkFlags Condition="'$(Configuration)' == 'Debug'"  >$(CMakeConfigurationWasiFlags)</CMakeConfigurationLinkFlags>
      <CMakeConfigurationLinkFlags Condition="'$(Configuration)' == 'Release'">-O2</CMakeConfigurationLinkFlags>

      <CMakeBuildRuntimeConfigureCmd>cmake $(MSBuildThisFileDirectory)runtime</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd Condition="'$(OS)' == 'Windows_NT'">cmake -G Ninja $(MSBuildThisFileDirectory)runtime</CMakeBuildRuntimeConfigureCmd>

      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DWASI_SDK_PREFIX=$(WASI_SDK_PATH)</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DCMAKE_SYSROOT=$(WASI_SDK_PATH)share/wasi-sysroot</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DCMAKE_CXX_FLAGS="--sysroot=$(WASI_SDK_PATH)share/wasi-sysroot"</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DCMAKE_TOOLCHAIN_FILE=$(WASI_SDK_PATH)share/cmake/wasi-sdk.cmake</CMakeBuildRuntimeConfigureCmd>

      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_WASICC_FLAGS=&quot;$(CMakeConfigurationWasiFlags)&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_LINK_FLAGS=&quot;$(CMakeConfigurationLinkFlags)&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_WASM_OPT_FLAGS=&quot;@(WasmOptConfigurationFlags, ';')&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DMONO_INCLUDES=&quot;$(MonoArtifactsPath)include/mono-2.0&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DMONO_OBJ_INCLUDES=&quot;$(MonoObjDir.TrimEnd('\/'))&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DICU_LIB_DIR=&quot;$(ICULibDir.TrimEnd('\/'))&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DMONO_ARTIFACTS_DIR=&quot;$(MonoArtifactsPath.TrimEnd('\/'))&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DNATIVE_BIN_DIR=&quot;$(NativeBinDir.TrimEnd('\/'))&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd Condition="'$(WasmEnableSIMD)' == 'true'">$(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_COMPILE_OPTIONS=&quot;-msimd128&quot; -DCONFIGURATION_INTERPSIMDTABLES_LIB=&quot;simd&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd Condition="'$(WasmEnableSIMD)' != 'true'">$(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_INTERPSIMDTABLES_LIB=&quot;nosimd&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd Condition="'$(WasmEnableThreads)' == 'true'">$(CMakeBuildRuntimeConfigureCmd) -DDISABLE_THREADS=0</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd Condition="'$(OS)' == 'Windows_NT'">call &quot;$(RepositoryEngineeringDir)native\init-vs-env.cmd&quot; wasm &amp;&amp; $(CMakeBuildRuntimeConfigureCmd)</CMakeBuildRuntimeConfigureCmd>

      <CMakeOptions Condition="'$(MonoVerboseBuild)' != ''">-v</CMakeOptions>
      <CMakeBuildRuntimeCmd>cmake --build . --config $(Configuration) $(CmakeOptions)</CMakeBuildRuntimeCmd>
      <CMakeBuildRuntimeCmd Condition="'$(OS)' == 'Windows_NT'">call &quot;$(RepositoryEngineeringDir)native\init-vs-env.cmd&quot; &amp;&amp; $(CMakeBuildRuntimeCmd)</CMakeBuildRuntimeCmd>
    </PropertyGroup>

    <ItemGroup>
      <_FilesToCopy Include="$(BrowserProjectRoot)runtime\runtime.c"                 DestinationFolder="$(NativeBinDir)src" />
      <_FilesToCopy Include="$(BrowserProjectRoot)runtime\pinvoke.c"                 DestinationFolder="$(NativeBinDir)src" />
      <_FilesToCopy Include="$(MSBuildThisFileDirectory)runtime/driver.c"            DestinationFolder="$(NativeBinDir)src" />
      <_FilesToCopy Include="$(MSBuildThisFileDirectory)runtime/main.c"              DestinationFolder="$(NativeBinDir)src" />
      <_FilesToCopy Include="$(MSBuildThisFileDirectory)runtime/stubs.c"             DestinationFolder="$(NativeBinDir)src" />
      <_FilesToCopy Include="$(MSBuildThisFileDirectory)runtime/synthetic-pthread.c" DestinationFolder="$(NativeBinDir)src" />

      <_FilesToCopy Include="$(WasiProjectRoot)mono-include\driver.h"           DestinationFolder="$(NativeBinDir)include\wasm" />
      <_FilesToCopy Include="$(BrowserProjectRoot)runtime\gc-common.h"               DestinationFolder="$(NativeBinDir)include\wasm" />
      <_FilesToCopy Include="$(BrowserProjectRoot)runtime\runtime.h"                 DestinationFolder="$(NativeBinDir)include\wasm" />
      <_FilesToCopy Include="$(BrowserProjectRoot)runtime\pinvoke.h"                 DestinationFolder="$(NativeBinDir)include\wasm" />
    </ItemGroup>

    <Copy SourceFiles="$(PInvokeTableFile)"
          DestinationFolder="$(MonoObjDir)"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="$(InterpToNativeTableFile)"
          DestinationFolder="$(MonoObjDir)"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="@(_FilesToCopy)"
          DestinationFolder="%(_FilesToCopy.DestinationFolder)"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="@(ICULibFiles);
                       @(ICULibNativeFiles);
                       @(_WasmArchivedTimezones);"
          DestinationFolder="$(NativeBinDir)"
          SkipUnchangedFiles="true" />

    <Exec Command="$(CMakeBuildRuntimeConfigureCmd)" WorkingDirectory="$(NativeBinDir)" />
    <Exec Command="$(CMakeBuildRuntimeCmd)"  WorkingDirectory="$(NativeBinDir)" />

    <ItemGroup>
      <IcuDataFiles Include="$(NativeBinDir)*.dat" />
      <WasmSrcFiles Include="$(NativeBinDir)src\*.c;" />
      <WasmSrcFiles Include="$(_WasiDefaultsRspPath);$(_WasiCompileRspPath);$(_WasiLinkRspPath);$(NativeBinDir)src\wasm-props.json" />
      <WasmHeaderFiles Include="$(NativeBinDir)include\wasm\*.h" />
    </ItemGroup>

    <Copy SourceFiles="$(NativeBinDir)dotnet.wasm;"
          DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="@(IcuDataFiles);@(ICULibNativeFiles);@(_WasmArchivedTimezones)"
          DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="@(WasmSrcFiles)"
          DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)src"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="@(WasmHeaderFiles)"
          DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)include\wasm"
          SkipUnchangedFiles="true" />
  </Target>
</Project>
